import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Like, Repository } from 'typeorm';
import { RequestStatusCode, RequestStatusMessage } from '../constants';
import { ReturnResult } from '../base/return-result';
import {
  YixianTongFields,
  YixiantongFieldsGoods,
  YixiantongFieldsGoodsService,
} from '../entities/yixiantong';
import { ColumnStatus, YixiantongCities, YixiantongFieldItem } from '../entities/yixiantong.type';

@Injectable()
export class YixiantongService {
  constructor(
    @InjectRepository(YixianTongFields)
    private yixiantongFieldsRepository: Repository<YixianTongFields>,
    @InjectRepository(YixiantongFieldsGoods)
    private yixiantongFieldsGoodsRepository: Repository<YixiantongFieldsGoods>,
    @InjectRepository(YixiantongFieldsGoodsService)
    private yixiantongFieldsGoodsService: Repository<YixiantongFieldsGoodsService>,
  ) {}

  public async getHomeDatas(cityId?: string): Promise<ReturnResult<any>> {
    const yixiantongFieldsGoods = await this._getYixiantongFieldsGoodList(cityId as YixiantongCities);

    return new ReturnResult(
      RequestStatusCode.Success,
      RequestStatusMessage.Success,
      {
        foodDatas: yixiantongFieldsGoods.filter(item => item.field === YixiantongFieldItem.Food).slice(0, 20),
        hotelDatas: yixiantongFieldsGoods.filter(item => item.field === YixiantongFieldItem.Hotel).slice(0, 20),
        massageDatas: yixiantongFieldsGoods.filter(item => item.field === YixiantongFieldItem.Massage).slice(0, 20),
        ktvDatas: yixiantongFieldsGoods.filter(item => item.field === YixiantongFieldItem.Ktv).slice(0, 20),
        viewDatas: yixiantongFieldsGoods.filter(item => item.field === YixiantongFieldItem.View).slice(0, 20),
      },
    );
  }

  public async getListDatas(cityId: YixiantongCities, field: YixiantongFieldItem) {
    const data = await this._getYixiantongFieldsGoodList(cityId, field);
    return new ReturnResult(
      RequestStatusCode.Success,
      RequestStatusMessage.Success,
      data.slice(0, 20)
    );
  }

  public async getFields() {
    const data = await this.yixiantongFieldsRepository.find({
      where: {
        status: ColumnStatus.Normal,
      },
      order: {
        createTime: 'DESC', // 按照创建时间降序排序
        updateTime: 'DESC',
      },
    });

    return new ReturnResult(
      RequestStatusCode.Success,
      RequestStatusMessage.Success,
      data
    );
  }

  public async createField(field: YixianTongFields) {
    try {
      if (!field?.name?.length) {
        throw new Error('"name" 不能为空');
      }
      field.createTime = new Date();
      field.updateTime = new Date();

      const newField = await this.yixiantongFieldsRepository.save(field);
      return new ReturnResult(
        RequestStatusCode.Success,
        RequestStatusMessage.Success,
        newField
      );
    } catch (e) {
      return new ReturnResult(
        RequestStatusCode.OperateError,
        `${RequestStatusMessage.OperateError}: ${e.message}`,
        null,
        'Fail'
      );
    }
  }

  private async _getYixiantongFieldsGoodList(
    cityName?: string,
    field?: YixiantongFieldItem
  ) {
    const cityInfosResult = await this.getFields();
    const cityInfos = cityInfosResult.getData();

    const data = await this.yixiantongFieldsGoodsRepository.find({
      where: {
        cityName: cityInfos.find(item => item.name === cityName) ? cityName : undefined,
        field,
        status: 1,
      },
      select: ['id', 'field', 'defaultPrice', 'price', 'name', 'score', 'star', 'createTime', 'img', 'cityName', 'keywords'],
      take: 100, // 限制返回的数据条数
    });
    return data.map(item => {
      return {
        ...item,
        cityName: cityInfos.find(cityInfo => cityInfo.name === item.cityName)?.aliasName ?? item.cityName,
      };
    });
  }

  public async getDetail(paramId: string) {
    try {
      const id: number = Number(paramId);
      const targetData = await this.yixiantongFieldsGoodsRepository.findOne({
        where: { id, status: 1 },
      });

      if (!targetData?.banners?.length) {
        targetData.setBanners([]);
      }
      const targetDataService = await this.yixiantongFieldsGoodsService.findOne({
        where: { id: targetData.id, status: 1 },
        select: ['parking', 'wifi'],
      });

      return new ReturnResult(
        RequestStatusCode.Success,
        RequestStatusMessage.GetDetailSuccess,
        {
          ...targetData,
          service: targetDataService ?? {},
        }
      );
    } catch (e) {
      return new ReturnResult(
        RequestStatusCode.OperateError,
        `${RequestStatusMessage.GetDetailError}: ${e.message}`,
        null,
        'Fail'
      );
    }
  }

  public async searchAction(keyword: string) {
    try {
      const cityInfosResult = await this.getFields();
      const cityInfos = cityInfosResult.getData();
      const yixiantongFieldsGoods = await this.yixiantongFieldsGoodsRepository.find({
        where: {
          name: Like(`%${keyword}%`),
          status: 1,
        },
        select: ['id', 'field', 'defaultPrice', 'price', 'name', 'score', 'star', 'createTime', 'img', 'cityName', 'keywords'],
      });
      const dataList = yixiantongFieldsGoods.map(item => {
        return {
          ...item,
          cityName: cityInfos.find(cityInfo => cityInfo.name === item.cityName)?.aliasName ?? item.cityName,
        };
      });
      return new ReturnResult(
        RequestStatusCode.Success,
        RequestStatusMessage.Success,
        {
          foodDatas: dataList.filter(item => item.field === YixiantongFieldItem.Food).slice(0, 20),
          hotelDatas: dataList.filter(item => item.field === YixiantongFieldItem.Hotel).slice(0, 20),
          massageDatas: dataList.filter(item => item.field === YixiantongFieldItem.Massage).slice(0, 20),
          ktvDatas: dataList.filter(item => item.field === YixiantongFieldItem.Ktv).slice(0, 20),
          viewDatas: dataList.filter(item => item.field === YixiantongFieldItem.View).slice(0, 20),
        }
      );
    } catch (e) {
      return new ReturnResult(
        RequestStatusCode.OperateError,
        `${RequestStatusMessage.OperateError}: ${e.message}`,
        null,
        'Fail'
      );
    }
  }
}
